"""
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    created by lane.chang on '10/09/2024'
    comment: agent演化接口
"""
import asyncio
import ujson
from fastapi import BackgroundTasks
from fastapi import APIRouter, Request, Body, Depends, Query, responses

from config import Config
from project.lib.decorator import api_common, exec_duration
from project.lib.common import Session, get_session
from project.core.function import json_response
from project.model.basic import Question, Knowledge
from project.model.flow import Flow
from project.model.basic import User
from project.service.anget import AgentService
from project.service.agents.interaction import Interaction
from project.service.agents.agent import Agent
from project.lib.common import get_redis, logger
from project.core.log import Colors
from project.service.agents.gather import GatherService
from project.service.agents.answer import AnswerService
from project.model.chatgpt import ChatGpt


agent_router = APIRouter(prefix='', tags=['Agent'])


@agent_router.post('/agent/global/intent', summary='全局意图')
@api_common(doc_replace=(('{0}', Config.HTTP_DOC_FIX),))
@exec_duration(add_return=True)
async def get_global_intent(request: Request,
                            user: User = Body(..., title='用户信息'),
                            user_message: str = Body(..., title='用户话术'),
                            flows: list[Flow] = Body(..., title='服务流程列表'),
                            knowledge: Knowledge = Body(None, title='知识库'),
                            chat_model_name: str = Body(Config.DEFAULT_MODEL, title='模型名称'),
                            memories_record: bool = Body(True, title='记录记忆'),
                            agent_profile: str = Body('你是一个在酒店房间里的人工智能机器人', title='agent角色定位'),
                            user_role: str = Body('客人', title='用户的角色称谓'),
                            session=None):
    """
    **desc**: 全局意图识别

    **url**: http(s)://{0}.udicaria.com/agent/global/intent

    **method**: POST

    **params**:

        <body>:
            user: {
                bot_id: 机器id(udi/careana)
                user_id: 用户id
                dev_id: 设备id
            }
            user_message: 用户文本
            flows: 酒店服务列表
            knowledge: {
                key: 知识库key
                questions: 知识库问答列表
            }
            chat_model_name: 模型名称
            memories_record: 是否记录对话
            agent_profile: agent角色定位
            user_role: 用户的角色称谓

    **return**:json数据结构::

        {
            code: 0(成功)/非0(失败)
            message: 成功返回success, 否则返回error信息
            data: [
                {
                    intent: 意图 report(报告)/service(服务流程)/video_link(视频连接)/chat(聊天)
                    action: 服务名称
                    response: 数字人话术
                }
            ]
            exec_time: 接口后端处理时长
        }
    """
    params = {
        'user': user.dict(),
        'user_message': user_message,
        'memories_record': memories_record,
        'flows': [v.dict() for v in flows],
        'knowledge': knowledge.dict(),
        'agent_profile': agent_profile,
        'user_role': user_role
    }
    logger.info(ujson.dumps(params, ensure_ascii=False, indent=4), font_color=Colors.PURPLE.value)
    ret_data = await AgentService.get_global_intent(user, user_message, flows,
                                                    knowledge=knowledge,
                                                    session=session,
                                                    chat_model_name=chat_model_name,
                                                    memories_record=memories_record,
                                                    agent_profile=agent_profile,
                                                    user_role=user_role)

    return json_response(data=ret_data)


@agent_router.post('/agent/flow/policy', summary='流程决策')
@api_common(doc_replace=(('{0}', Config.HTTP_DOC_FIX),))
@exec_duration(add_return=True)
async def do_flow_policy(request: Request,
                         user: User = Body(..., title='用户信息'),
                         user_message: str = Body(..., title='用户话术'),
                         flow: Flow = Body(..., title='服务流程'),
                         knowledge: Knowledge = Body(None, title='知识库'),
                         chat_model_name: str = Body(Config.DEFAULT_MODEL, title='模型名称'),
                         agent_profile: str = Body('你是一个在酒店房间里的人工智能机器人', title='agent角色定位'),
                         user_role: str = Body('客人', title='用户的角色称谓'),
                         is_init: bool = Body(False, title='是否初始化'),
                         memories_record: bool = Body(True, title='记录记忆'),
                         session=None):
    """
    **desc**: 流程决策

    **url**: http(s)://{0}.udicaria.com/agent/flow/policy

    **method**: POST

    **params**:

        <body>:
            user: {
                bot_id: 机器id(udi/careana/helper)
                user_id: 用户id
                dev_id: 设备id
            }
            user_message: 用户文本
            flow: {
                code: 流程编号
                title: 流程名称,
                sop:
                parameters: 参数列表
            } 流程信息
            knowledge: {
                key: 知识库key
                questions: 知识库问答列表
            }
            chat_model_name: 模型名称
            agent_profile: agent角色定位
            user_role: 用户的角色称谓

    **return**:json数据结构::

        {
            code: 0(成功)/非0(失败)
            message: 成功返回success, 否则返回error信息
            data: {
                response: 数字人话术

            }
            exec_time: 接口后端处理时长
        }
    """
    data = await AgentService.do_flow_policy(user, user_message, flow, knowledge,
                                             is_init=is_init,
                                             memories_record=memories_record,
                                             chat_model_name=chat_model_name,
                                             agent_profile=agent_profile,
                                             user_role=user_role,
                                             session=session)

    return json_response(data=data)


@agent_router.post('/agent/flow/dst', summary='流程参数')
@api_common(doc_replace=(('{0}', Config.HTTP_DOC_FIX),))
@exec_duration(add_return=True)
async def do_flow_dst(request: Request,
                      user: User = Body(..., title='用户信息'),
                      response: str = Body(..., title='agent话术'),
                      flow: Flow = Body(..., title='服务流程'),
                      chat_model_name: str = Body(Config.DEFAULT_MODEL, title='模型名称'),
                      agent_profile: str = Body('你是一个在酒店房间里的人工智能机器人', title='agent角色定位'),
                      user_role: str = Body('客人', title='用户的角色称谓')):
    """
    **desc**: 流程参数

    **url**: http(s)://{0}.udicaria.com/agent/flow/dst

    **method**: POST

    **params**:

        <body>:
            user: {
                bot_id: 机器id(udi/careana/helper)
                user_id: 用户id
                dev_id: 设备id
            }
            response: agent话术
            flow: {
                code: 流程编号
                title: 流程名称,
                sop:
                parameters: 参数列表
            } 流程信息
            chat_model_name: 模型名称
            agent_profile: agent角色定位
            user_role: 用户角色称谓

    **return**:json数据结构::

        {
            code: 0(成功)/非0(失败)
            message: 成功返回success, 否则返回error信息
            data: {
                selected_params:
            }
            exec_time: 接口后端处理时长
        }
    """
    data = await Interaction.dst(user, response, flow, chat_model_name=chat_model_name, agent_profile=agent_profile, user_role=user_role)

    return json_response(data={"selected_params": ujson.dumps(data, ensure_ascii=False)})


@agent_router.post('/agent/flow/interaction', summary='流程交互')
@api_common(doc_replace=(('{0}', Config.HTTP_DOC_FIX),))
@exec_duration(add_return=True)
async def do_flow_interaction(request: Request,
                              user: User = Body(..., title='用户信息'),
                              user_message: str = Body(..., title='用户话术'),
                              flow: Flow = Body(..., title='服务流程'),
                              knowledge: Knowledge = Body(None, title='知识库'),
                              chat_model_name: str = Body(Config.DEFAULT_MODEL, title='模型名称'),
                              is_init: bool = Body(False, title='是否初始化'),
                              memories_record: bool = Body(True, title='记录记忆'),
                              agent_profile: str = Body('你是一个在酒店房间里的人工智能机器人', title='agent角色定位'),
                              user_role: str = Body('客人', title='用户的角色称谓'),
                              session=None):
    """
    **desc**: 流程交互

    **url**: http(s)://{0}.udicaria.com/agent/flow/interaction

    **method**: POST

    **params**:

        <body>:
            user: {
                bot_id: 机器id(udi/careana/helper)
                user_id: 用户id
                dev_id: 设备id
            }
            user_message: 用户文本
            flow: {
                code: 流程编号
                title: 流程名称,
                sop:
                parameters: 参数列表
            } 流程信息
            knowledge: {
                key: 知识库key
                questions: 知识库问答列表
            }

    **return**:json数据结构::

        {
            code: 0(成功)/非0(失败)
            message: 成功返回success, 否则返回error信息
            data: {
                response: 数字人话术

            }
            exec_time: 接口后端处理时长
        }
    """
    data = await AgentService.do_flow_interaction(user, user_message, flow, knowledge, is_init,
                                                  chat_model_name=chat_model_name, memories_record=memories_record, agent_profile=agent_profile, user_role=user_role,
                                                  session=session)

    return json_response(data=data)


@agent_router.post('/agent/user/memories/add', summary='新增用户记忆')
@api_common(doc_replace=(('{0}', Config.HTTP_DOC_FIX),))
@exec_duration(add_return=True)
async def add_user_memories(request: Request,
                            user: User = Body(..., title='用户信息'),
                            user_message: str = Body('', title='用户话术'),
                            agent_message: str = Body('', title='agent话术'),
                            agent_profile: str = Body('你是一个在酒店房间里的人工智能机器人', title='agent角色定位'),
                            user_role: str = Body('客人', title='用户的角色称谓')):
    """
    **desc**: 新增用户记忆

    **url**: http(s)://{0}.udicaria.com/agent/user/memories/add

    **method**: POST

    **params**:

        <body>:
            user: {
                bot_id: 机器id(udi/careana)
                user_id: 用户id
                dev_id: 设备id
            }
            user_message: 用户话术
            agent_message: agent话术

    **return**:json数据结构::

        {
            code: 0(成功)/非0(失败)
            message: 成功返回success, 否则返回error信息
            data:
            exec_time: 接口后端处理时长
        }
    """
    agent = Agent(user, user_message, agent_profile=agent_profile, user_role=user_role)
    if user_message:
        agent.add_user_memories(agent.format(user_message))
    if agent_message:
        agent.add_user_memories(agent.format(agent_message, _type='out'))

    return json_response()


@agent_router.post('/agent/user/memories/list', summary='查询用户记忆')
@api_common(doc_replace=(('{0}', Config.HTTP_DOC_FIX),))
@exec_duration(add_return=True)
async def get_user_memories(request: Request,
                            user: User = Body(..., title='用户信息'),
                            count: int = Body(10, title='')):
    """
    **desc**: 查询用户记忆

    **url**: http(s)://{0}.udicaria.com/agent/user/memories/list

    **method**: POST

    **params**:

        <body>:
            user: {
                bot_id: 机器id(udi/careana)
                user_id: 用户id
                dev_id: 设备id
            }
            count: 数量

    **return**:json数据结构::

        {
            code: 0(成功)/非0(失败)
            message: 成功返回success, 否则返回error信息
            data:
            exec_time: 接口后端处理时长
        }
    """
    agent = Agent(user, user_message='')
    items = agent.load_user_memories(_type='list', count=count)

    return json_response(data=items)


@agent_router.post('/agent/user/memories/init', summary='清空用户记忆')
@api_common(doc_replace=(('{0}', Config.HTTP_DOC_FIX),))
@exec_duration(add_return=True)
async def init_user_memories(request: Request, dev_id: str = Body(..., title='设备id', embed=True)):
    """
    **desc**: 清空用户记忆

    **url**: http(s)://{0}.udicaria.com/agent/user/memories/init

    **method**: POST

    **params**:

        <body>:
            dev_id: 设备id

    **return**:json数据结构::

        {
            code: 0(成功)/非0(失败)
            message: 成功返回success, 否则返回error信息
            data:
            exec_time: 接口后端处理时长
        }
    """
    rds = get_redis()
    keys = rds.keys(f'interaction_memories_{dev_id}*')
    for key in keys:
        rds.delete(key)

    return json_response()


@agent_router.get('/agent/knowledge', summary='知识库信息')
@api_common(doc_replace=(('{0}', Config.HTTP_DOC_FIX),))
@exec_duration(add_return=True)
async def get_knowledge(request: Request,
                          key: str = Query(..., title='知识库key')):
    """
    **desc**: 知识库信息

    **url**: http(s)://{0}.udicaria.com/agent/knowledge

    **method**: POST

    **params**:

        <body>:
            questions: [
                {
                    index:
                    content:
                }
            ]知识库列表

    **return**:json数据结构::

        {
            code: 0(成功)/非0(失败)
            message: 成功返回success, 否则返回error信息
            data:
            exec_time: 接口后端处理时长
        }
    """
    knowledge = Knowledge(key=key)
    data = await knowledge.get_info()

    return json_response(data=data)


@agent_router.post('/agent/knowledge/flush', summary='知识库刷新')
@api_common(doc_replace=(('{0}', Config.HTTP_DOC_FIX),))
@exec_duration(add_return=True)
async def flush_knowledge(request: Request,
                          background_tasks: BackgroundTasks,
                          key: str = Body(..., title='知识库key'),
                          questions: list[Question] = Body(..., title='知识库列表')):
    """
    **desc**: 刷新知识库

    **url**: http(s)://{0}.udicaria.com/agent/knowledge/flush

    **method**: POST

    **params**:

        <body>:
            key: 知识库key
            questions: [
                {
                    index:
                    content:
                }
            ]知识库列表

    **return**:json数据结构::

        {
            code: 0(成功)/非0(失败)
            message: 成功返回success, 否则返回error信息
            data:
            exec_time: 接口后端处理时长
        }
    """
    knowledge = Knowledge(key=key, questions=questions)
    background_tasks.add_task(knowledge.flush_vector_db)

    return json_response()


@agent_router.post('/agent/collect/advice', summary='搜集建议')
@api_common(doc_replace=(('{0}', Config.HTTP_DOC_FIX),))
@exec_duration(add_return=True)
async def do_collect_advice(request: Request,
                            background_tasks: BackgroundTasks,
                            user: User = Body(..., title='用户信息'),
                            user_message: str = Body(..., title='用户话术')):
    """
    **desc**: 搜集建议

    **url**: http(s)://{0}.udicaria.com/agent/collect/advice

    **method**: POST

    **params**:

        <body>:
            user: {
                bot_id: 机器id(udi/careana)
                user_id: 用户id
                dev_id: 设备id
            }
            user_message: 用户话术

    **return**:json数据结构::

        {
            code: 0(成功)/非0(失败)
            message: 成功返回success, 否则返回error信息
            data:
            exec_time: 接口后端处理时长
        }
    """
    def _collect_advice(_user, _user_message):
        """
        :param _user:
        :param _user_message:
        :return:
        """
        asyncio.run(GatherService.collect_advice(user=user, user_message=user_message))
    # 后台运行
    background_tasks.add_task(_collect_advice, _user=user, _user_message=user_message)

    return json_response()


@agent_router.post('/agent/yes_no/check', summary='YesNo判断')
@api_common(doc_replace=(('{0}', Config.HTTP_DOC_FIX),))
@exec_duration(add_return=True)
async def do_yes_no_check(request: Request, user_message: str = Body(..., title='用户话术', embed=True)):
    """
    **desc**: 判断用户是yes还是no

    **url**: http(s)://{0}.udicaria.com/agent/yes_no/check

    **method**: POST

    **params**:

        <body>:
            user_message: 用户话术

    **return**:json数据结构::

        {
            code: 0(成功)/非0(失败)
            message: 成功返回success, 否则返回error信息
            data: {
                reason: 推理过程
                answer: 需要/不需要/其它
            }
            exec_time: 接口后端处理时长
        }
    """
    result = await AnswerService.answer(user_message)

    return json_response(data=result)


@agent_router.post('/test', summary='YesNo判断')
@api_common(doc_replace=(('{0}', Config.HTTP_DOC_FIX),))
@exec_duration(add_return=True)
async def do_test(request: Request):
    """
    **desc**: 判断用户是yes还是no

    **url**: http(s)://{0}.udicaria.com/test

    **method**: POST

    **params**:

        <body>:
            user_message: 用户话术

    **return**:json数据结构::

        {
            code: 0(成功)/非0(失败)
            message: 成功返回success, 否则返回error信息
            data: {
                reason: 推理过程
                answer: 需要/不需要/其它
            }
            exec_time: 接口后端处理时长
        }
    """
    chat_gpt = ChatGpt(chat_model_name='Qwen2.5-14B-Instruct-GPTQ-Int8')
    stream = chat_gpt.llm_async_streaming(user_text='给我简单介绍一下唐朝')

    return responses.StreamingResponse(stream, media_type='text/plain')
